#include "s3c2440_lcd_controller.h"

#define HCLK 100

void lcd_pin_init(void) {
    /* 初始化引脚 : 背光引脚 */
    GPBCON &= ~0x3;
    GPBCON |= 0x01;

    /* LCD专用引脚 */
    GPCCON = 0xaaaaaaaa;
    GPDCON = 0xaaaaaaaa;

    /* PWREN */
    GPGCON |= (3 << 8);
}

void s3c2440_lcd_controller_init(p_lcd_params p_lcd_params) {
    int pixelplace;
    uint32 addr;

    printf("s3c2440_lcd_controller_init\r\n");
    lcd_pin_init();

    p_lcd_params->time_seq.vclk = 8;
    int clkval = HCLK / p_lcd_params->time_seq.vclk / 2 - 1 + 0.5;
    int bppmode = p_lcd_params->bpp == 16  ? 0xc
                  : p_lcd_params->bpp == 8 ? 0xb
                                           : 0xd;
    LCDCON1 = (clkval << 8) | (3 << 5) | (bppmode << 1);
    LCDCON2 = (p_lcd_params->time_seq.tvb - 1) << 24 |
              (p_lcd_params->yres - 1) << 14 |
              (p_lcd_params->time_seq.tvf - 1) << 6 |
              (p_lcd_params->time_seq.tvp - 1) << 0;

    LCDCON3 = (p_lcd_params->time_seq.thb - 1) << 19 |
              (p_lcd_params->xres - 1) << 8 |
              (p_lcd_params->time_seq.thf - 1) << 0;

    LCDCON4 = (p_lcd_params->time_seq.thp - 1) << 0;

    pixelplace = p_lcd_params->bpp == 24   ? (0)
                 : p_lcd_params->bpp == 15 ? (1)
                                           : (1 << 1);
    LCDCON5 =
        p_lcd_params->pins_pol.vclk << 10 | p_lcd_params->pins_pol.rgb << 7 |
        p_lcd_params->pins_pol.hsync << 9 | p_lcd_params->pins_pol.vsync << 8 |
        p_lcd_params->pins_pol.de << 6 | p_lcd_params->pins_pol.pwren << 5 |
        (1 << 11) | pixelplace;

    addr = p_lcd_params->fb_base & ~(1 << 31);
    LCDSADDR1 = (addr >> 1);

    addr = p_lcd_params->fb_base +
           p_lcd_params->xres * p_lcd_params->yres * p_lcd_params->bpp / 8;
    addr >>= 1;
    addr &= 0x1fffff;
    LCDSADDR2 = addr;
}

void s3c2440_lcd_controller_enable(void) {
	// GPBDAT |= (1<<0);
	LCDCON5 |= (1<<3);
	LCDCON1 |= (1<<0);
}

void s3c2440_lcd_controller_disable(void) {
	// GPBDAT &= ~(1<<0);
	LCDCON5 &= ~(1<<3);
	LCDCON1 &= ~(1<<0);
}

lcd_controller s3c2440_lcd_controller = {
    .name = "s3c2440",
    .init = s3c2440_lcd_controller_init,
    .enable = s3c2440_lcd_controller_enable,
    .disable = s3c2440_lcd_controller_disable,
};

void s3c2440_lcd_controller_add(void) {
    register_lcd_controller(&s3c2440_lcd_controller);
}
